package com.zh.modules.app.utils;

import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cglib.beans.BeanCopier;

import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 对象拷贝
 *
 * @author zhanxf
 * @date 2022/4/8
 */
@Slf4j
public class ConvertUtils {

    private static Map<String, BeanCopier> BEAN_COPIER_CACHE = Maps.newConcurrentMap();

    public static <T> T copyObject(Object source, Class<T> destinationClass) {
        try {
            T destination = destinationClass.getDeclaredConstructor().newInstance();
            BeanUtils.copyProperties(source,destination);
            return destination;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                 NoSuchMethodException e) {
            log.error("ConvertUtils error", e);
        }
        return null;
    }

    public static <D> D newInstance(Supplier<D> supplier, Consumer<D> consumer) {
        D d = supplier.get();
        if (consumer != null) {
            consumer.accept(d);
        }
        return d;
    }

    public static <S, D> D transfer(S s, Supplier<D> supplier) {
        return transfer(s, supplier, null);
    }

    public static <S, D> D transfer(S s, Supplier<D> supplier, BiConsumer<S, D> biConsumer) {
        if (s == null) {
            return null;
        }
        D d = supplier.get();
        BeanUtils.copyProperties(s, d);
        if (biConsumer != null) {
            biConsumer.accept(s, d);
        }
        return d;
    }

    public static <S, D> List<D> transfers(Collection<S> list, Supplier<D> supplier) {
        if (list == null) {
            return null;
        }
        return list.stream().map(mapper -> transfer(mapper, supplier)).collect(Collectors.toList());
    }

    public static <S, D> List<D> transfers(Collection<S> list, Supplier<D> supplier, BiConsumer<S, D> biConsumer) {
        if (list == null) {
            return null;
        }
        return list.stream().map(mapper -> transfer(mapper, supplier, biConsumer)).collect(Collectors.toList());
    }
}
